/*
 * Assignment2.cpp
 *
 * Example code for Assignment #2
 *
 *  Created on: Feb 13, 2014
 *      Author: Anthony Varghese
 */

/*
 * sequenceType enumeration type
 *
 */
enum sequenceType { dna, rna, protein };

#include <string>

/*
 * The SingleSequence struct is used to store a single sequence
 */
struct SingleSequence{
	std::string name;
	std::string seq;
	int length;
	double gccontent;
	sequenceType type;
};

#include<vector>


/*
 * Sequences class - A Sequences object will have an array of SingleSequence objects
 *
 */
class SequenceList{
public:
	/*
	 * Constructors
	 */
	SequenceList(){
	}
	SequenceList(std::vector<std::string>& v){
		datasize = v.size() / 2;
		capacity = datasize;
		data = new SingleSequence[datasize];
		for (int i=0; i<datasize; i++){
			data[i].name = v[i*2];
			data[i].seq  = v[i*2+1];
		}
	}
	SequenceList(int cap){
		if (cap <= 0)
			return;
		data = new SingleSequence[cap];
		capacity = cap;
		datasize = 0;
	}
	/*
	 * add method for list
	 */
	void addSequence(SingleSequence& s) {
		SingleSequence newSeq = s;
		if (datasize < capacity )
			data[datasize++] = newSeq;
	}

	/*
	 * get method for datasize data member
	 */
	int getListSize() const {
		return datasize;
	}

	/*
	 * This get method returns a reference
	 */
	const SingleSequence& get(int i) const {
		if (i>=0 && i < datasize)
			return data[i];
		throw OUT_OF_BOUNDS; // C++ has exceptions - you can even throw ints
	}
	void sortByName(){
	}
	void sortBySequence(){
	}
	void sortByLength(){
	}

private:
	SingleSequence* data;
	int datasize = 0;
	int capacity = 0;
	static const int OUT_OF_BOUNDS = -1;
};

/*
 * overriding the insertion operator "<<"
 */
#include <iostream>
std::ostream& operator<<(std::ostream& os, const SingleSequence& s){
	os << s.name << " " << s.seq << " " << s.length << " " << s.type;
	return os;
}
std::ostream& operator<<(std::ostream& os, const SequenceList& seqs){
	os << "  Sequences object " << std::endl;
	for (int i=0; i < seqs.getListSize(); i++ )
		os << "    " << (i+1) <<":  " << seqs.get( i ) << std::endl;
	return os;
}



int readinputfile( std::string f, std::vector<std::string>& v );

int main(){
	std::cout << "Assignment #2 Sequences:" << std::endl;
	std::string inputfile = "src/input.fasta";

	std::cout << "  1. Reading from file: \"" << inputfile << "\" ... ";

	std::vector<std::string> seqs;
	int number_of_sequences = readinputfile( inputfile, seqs );
	std::cout << " number of sequences in file is: " << number_of_sequences;
	std::cout << ". File has been read!" << std::endl;

	SequenceList* mysequences = new SequenceList( seqs );
	std::cout << *mysequences << std::endl;

	// Sort and print
	std::cout << "  2. Sorted by names:" << std::endl;
	SequenceList* sequencesByName = new SequenceList( *mysequences );
	sequencesByName->sortByName();
	std::cout << *sequencesByName << std::endl;

	// Sort and print
	std::cout << "  3. Sorted by sequence:" << std::endl;
	SequenceList* sequencesBySeq = new SequenceList( *mysequences );
	sequencesBySeq->sortBySequence();
	std::cout << *sequencesBySeq << std::endl;

	// Sort and print
	std::cout << "  4. Sorted by length:" << std::endl;
	SequenceList* namesByLength = new SequenceList( *mysequences );
	namesByLength->sortByLength();
	std::cout << *namesByLength << std::endl;

	std::cout << "  5. Original sequences:" << std::endl;
	std::cout << *mysequences;

	delete mysequences;
	delete sequencesByName;
	delete sequencesBySeq;
	delete namesByLength;

	std::cout << "... all done!" << std::endl;
}

#include <fstream>

int readinputfile( std::string f , std::vector<std::string>& v){

	std::ifstream input;
	input.open( f.c_str() );

	// Read first string in the file
	std::string s;
	input >> s;

	do {
		// These are for building a single sequence.
		std::string name;
		std::string sequence;

		// Check if what was read in was a comment/name
		if (s[0] == '>'){
			name = s.erase(0,1);  // remove the > character

			// read the rest of the line into name2
			std::string name2;
			std::getline( input, name2 );
			name = name + name2;

			// Read the next line
			input >> s;
			sequence = "";
		}
		while ( s[0] != '>' ){
			sequence = sequence + s;
			if (input.eof())
				break;
			// Read the next line
			input >> s;
		}
		// Debugging: std::cout << "read: " << name << ": " << sequence << std::endl;
		v.push_back( name );
		v.push_back( sequence );
	} while ( !input.eof() );
	input.close();
	return v.size()/2;
}
